package com.sprite.utils.mimetype;

import com.sprite.utils.UtilArray;
import com.sprite.utils.UtilString;
import com.sprite.utils.text.InsensitiveString;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author Jack
 * @since 1.2.4
 */
public class MimeType {
    private String mimeType;
    private String type;
    private String subtype;
    private LinkedHashMap<InsensitiveString, Object> parameter = new LinkedHashMap<>();

    public MimeType() {
    }

    public MimeType(String typStr) {
        init(typStr);
    }

    private void init(String contentType) {
        if (UtilString.isBlank(contentType)) {
            throw new IllegalArgumentException("mime type is null");
        }

        contentType = contentType.trim();

        int index = contentType.indexOf(';');
        if (index > 0) {
            mimeType = contentType.substring(0, index);
            contentType = contentType.substring(index + 1).trim();
            String[] typs = UtilString.tokenizeToStringArray(mimeType, "/");
            type = UtilArray.at(typs, 0, null);
            subtype = UtilArray.at(typs, 0, null);
        } else {
            mimeType = contentType;
            String[] typs = UtilString.tokenizeToStringArray(mimeType, "/");
            type = UtilArray.at(typs, 0, null);
            subtype = UtilArray.at(typs, 0, null);
            return;
        }

        char[] chs = contentType.toCharArray();

        boolean isValue = false;    // 是否是字段值
        int indexStart = 0;
        int offset = 0;
        String key = null;
        String value = null;
        boolean startQuote = false;   // 是否引号开头
        for (char ch : chs) {
            offset++;
            if (!isValue & ch == '=') {// 获取key
                key = new String(chs, indexStart, offset - 1);
                indexStart += offset;
                offset = 0;
                continue;
            }

            if (key != null) {// 获取value
                if (!isValue) {
                    if (ch != ' ') {// 首个非空格字符是value开始的地方
                        isValue = true;
                        offset = 1;
                        if (ch == '"') {// 跳过引号
                            indexStart++;
                            startQuote = true;
                        }

                    } else {// 跳过空格
                        indexStart++;
                    }
                } else {
                    if (startQuote) {
                        if (ch == '"') {
                            value = new String(chs, indexStart, offset - 1);
                        } else if (indexStart + offset == chs.length) {
                            value = new String(chs, indexStart, offset);
                        }
                    } else {
                        if (ch == ' ') {
                            value = new String(chs, indexStart, offset - 1);
                        } else if (indexStart + offset == chs.length) {
                            value = new String(chs, indexStart, offset);
                        }
                    }
                }

                if (value != null) {
                    putParam(key, value);
                    key = null;
                    value = null;
                    isValue = false;
                    startQuote = false;
                    indexStart += offset;
                    offset = 0;
                }
            }
        }
    }

    public void putParam(String key, Object value) {
        if (value == null) {
            return;
        }
        parameter.put(InsensitiveString.insensitive(key), value);
    }

    public String getParam(String key) {
        return toString(parameter.get(InsensitiveString.insensitive(key)));
    }

    public String getMimeType() {
        return mimeType;
    }

    public void setMimeType(String mimeType) {
        init(mimeType);
    }

    public String getType() {
        return type;
    }

    public String getSubtype() {
        return subtype;
    }

    public String toString() {
        StringBuffer ct = new StringBuffer(mimeType);
        for (Map.Entry<InsensitiveString, Object> entry : parameter.entrySet()) {
            ct.append("; ").append(entry.getKey()).append("=\"").append(toString(entry.getValue())).append("\"");
        }

        return ct.toString();
    }
    /**
     * @param value
     * @return
     * @since 1.2.4
     */
    private String toString(Object value) {
        if (value == null) {
            return null;
        }
        return value.toString();
    }
}
